package uk.ac.ebi.das.uniprot.image.util;

import uk.ac.ebi.das.uniprot.image.controller.AbstractPainter;

import java.util.HashMap;

/**
 * Created by IntelliJ IDEA.
 * User: ljgarcia
 * Date: 01-Apr-2011
 * Time: 11:38:44
 * To change this template use File | Settings | File Templates.
 */
public class FeatureTypeConfigHelper {
    public static HashMap<String, String> featureNameMap = new HashMap<String, String>();
    private static boolean displaySet = false;

    /**
     * Returns the greatest layer defined for features.
     * @return
     */
    public static int getMaxLayer() {
        int max = 0;
        for (FeatureTypeConfig type: FeatureTypeConfig.values()) {
            max = type.getNonOverlappingLayer() > max ? type.getNonOverlappingLayer() : max;
        }
        return max;
    }
    /**
     * Fetch a feature type by its cvId.
     * @param cvId
     * @param id
     * @return
     */
    public static FeatureTypeConfig fetchByCvId(String cvId, String id) {
        for (FeatureTypeConfig type: FeatureTypeConfig.values()) {
            if (cvId.equals("SO:0000417")) {
                if (id != null) {
                    if (id.toUpperCase().indexOf(FeatureTypeConfig.CA_BIND.getType().toUpperCase()) != -1) {
                        return FeatureTypeConfig.CA_BIND;
                    } else if (id.toUpperCase().indexOf(FeatureTypeConfig.DNA_BIND.getType().toUpperCase()) != -1) {
                        return FeatureTypeConfig.DNA_BIND;
                    } else if (id.toUpperCase().indexOf(FeatureTypeConfig.NP_BIND.getType().toUpperCase()) != -1) {
                        return FeatureTypeConfig.NP_BIND;
                    } else if (id.toUpperCase().indexOf(FeatureTypeConfig.ZN_FING.getType().toUpperCase()) != -1) {
                        return FeatureTypeConfig.ZN_FING;
                    }
                }
                return FeatureTypeConfig.DOMAIN;
            } else {
                if (cvId.toUpperCase().equals(type.getCvId().toUpperCase())) {
                    return type;
                }
            }
        }
        return FeatureTypeConfig.UNKNOWN;
    }

    /**
     * Fetch a feature type by its name.
     * @param name
     * @return
     */
     public static FeatureTypeConfig fetchByName(String name) {
         for (FeatureTypeConfig type: FeatureTypeConfig.values()){
             if (name.toUpperCase().equals(type.getName().toUpperCase())) {
                 return type;
             }
         }
         return FeatureTypeConfig.UNKNOWN;
    }

    /**
     * Fetch a feature type by its type.
     * @param type
     * @return
     */
    public static FeatureTypeConfig fetchByType(String type) {
        for (FeatureTypeConfig featureType: FeatureTypeConfig.values()){
            if (type.toUpperCase().equals(featureType.getType().toUpperCase())) {
                return featureType;
            }
        }
        return FeatureTypeConfig.UNKNOWN;
    }

    /**
     * Applies positions, rows, and radius for row style.
     */
    public static void applyRowStyle() {
        if (!FeatureTypeConfigHelper.displaySet) {
            initDisplay();
        }
        int rowUp = -1;
        int rowDown = 1;
        for (FeatureTypeConfig type: FeatureTypeConfig.values()) {
            if (type.getDisplay()) { //display it
                //calculate row rows only for displayed features
                if (type.getPositionRows().equals(Position.UP.getPosition())) {
                    type.setRowRows(rowUp);
                    rowUp--;
                } else if (type.getPositionRows().equals(Position.DOWN.getPosition())) {
                    type.setRowRows(rowDown);
                    rowDown++;
                }
            }
            //apply style
            type.setRowsStyle();
        }
    }

    /**
     * Applies positions, rows, and radius for centered style.
     */
    public static void applyCenteredStyle() {
        if (AbstractPainter.CENTERED_SAME_SIZE) {
            applyCenteredSameSizeStyle();
        } else {
            if (!FeatureTypeConfigHelper.displaySet) {
                initDisplay();
            }
            int centeredUp = -4;
            int centeredDown = 4;
            int radius = 8;
            for (FeatureTypeConfig type: FeatureTypeConfig.values()) {
                if (type.getDisplay()) { //display it
                    //calculate centered rows only for displayed features
                    if (type.getPositionCentered().equals(Position.MIDDLE.getPosition())) {
                        type.setRowCentered(0);
                    } else if (type.getPositionCentered().equals(Position.UP.getPosition())) {
                        type.setRowCentered(centeredUp);
                        centeredUp--;
                    } else if (type.getPositionCentered().equals(Position.DOWN.getPosition())) {
                        type.setRowCentered(centeredDown);
                        centeredDown++;
                    }
                    //calculate radius only for displayed features
                    type.setRadiusCentered(radius);
                    radius += 4;
                }
                //apply style
                type.setCenteredStyle();
            }
        }
    }

    /**
     * Applies positions, rows, and radius for centered style.
     */
    private static void applyCenteredSameSizeStyle() {
        if (!FeatureTypeConfigHelper.displaySet) {
            initDisplay();
        }
        int centeredUp = -2;
        int centeredDown = 2;
        int radius = AbstractPainter.RECTANGLE_HEIGHT;
        for (FeatureTypeConfig type: FeatureTypeConfig.values()) {
            if (type.getDisplay()) { //display it
                //calculate centered rows only for displayed features
                if (type.getPositionCentered().equals(Position.MIDDLE.getPosition())) {
                    type.setRowCentered(0);
                } else if (type.getPositionCentered().equals(Position.UP.getPosition())) {
                    type.setRowCentered(centeredUp);
                } else if (type.getPositionCentered().equals(Position.DOWN.getPosition())) {
                    type.setRowCentered(centeredDown);
                }
                //calculate radius only for displayed features
                type.setRadiusCentered(radius);
            }
            //apply style
            type.setCenteredStyle();
        }
        AbstractPainter.CENTERED_STYLE_MAX_RADIUS = radius * (1+centeredDown);
    }

    /**
     * Specifies position and radius for shapes in non overlapping style.
     * Although row is defined, it will be not used since, in order to avoid overlapping, it is necessary to
     * calculate the row for each feature rather than use the same one depending on the feature type.
     */
    public static void applyNonOverlappingStyle() {
        if (!FeatureTypeConfigHelper.displaySet) {
            initDisplay();
        }
        for (FeatureTypeConfig type: FeatureTypeConfig.values()) {
            type.setNonOverlappingStyle();
        }
    }

    /**
     * Sets display in true or false depending on what the properties file says
     */
    public static void initDisplay() {
        FeatureTypeConfigHelper.displaySet = true;

        int featuresToDisplay = 0;
        for (FeatureTypeConfig type: FeatureTypeConfig.values()) {
            if (AbstractPainter.ALL_FEATURES) {
                type.setDisplay(true);
                featuresToDisplay ++;
            } else {
                if (RetrievalHelper.getFeatureDisplay(type)) {
                    type.setDisplay(true);
                    featuresToDisplay ++;
                } else {
                    type.setDisplay(false);
                }
            }
        }
        AbstractPainter.ROWS_STYLE_MAX_ROW = featuresToDisplay+1;
        AbstractPainter.CENTERED_STYLE_MAX_RADIUS = featuresToDisplay * 4;
    }

    public static int getMaxVisibleCenteredRowNoMiddle() {
        int max = 0;
        for (FeatureTypeConfig type: FeatureTypeConfig.values()) {
            if (type.getDisplay() && !type.getPositionCentered().equals(Position.MIDDLE.getPosition())) {
                if (Math.abs(type.getRowCentered()) > max ) {
                    max = Math.abs(type.getRowCentered());
                }
            }
        }
        return max;
    }
}
